﻿#define HAS_VIEWED_ANNOTATIONS

using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;

using SharedGenomics.Core;
using SharedGenomics.Core.Configuration;
using SharedGenomics.Annotations;
using SharedGenomics.Workbench.Aspects;
using SharedGenomics.Workbench.Services;
using SharedGenomics.Workbench.Models;
using SharedGenomics.Workbench.Annotations;

namespace SharedGenomics.Workbench.Core.Configuration
{
    public class ServicesContainerConfigurationStrategy : IContainerConfigurationStrategy
    {
        public void Configure(ContainerConfigurationContext context)
        {
            var container = context.Container;

            //BITS upload service
            container.RegisterType<IFileUpload, BITSFileUpload>();

            //repositories
            //setup cache interceptor on container
            container.RegisterType<ICachingStrategy, LoginCachingStrategy>();
            container.AddNewExtension<Interception>();
            container.Configure<Interception>().SetDefaultInterceptorFor<IDataSetRepository>(new InterfaceInterceptor());
            container.Configure<Interception>().SetDefaultInterceptorFor<IFileSetRepository>(new InterfaceInterceptor());
            container.Configure<Interception>().SetDefaultInterceptorFor<IFileSchemaRepository>(new InterfaceInterceptor());

            container.RegisterType<IFileSchemaRepository, FileSchemaRepository>();
            container.RegisterType<IFileSetRepository, FileSetRepository>();
            container.RegisterType<IDataSetRepository, DataSetRepository>();

            //job details repository - the implementation to use depends on the config file
            if (Properties.Settings.Default.LoadAnalysisFromFile)
            {
                string resultsFilePath = Properties.Settings.Default.LocalJobDetailsFilePath;
                IJobDetailsRepository repository = new LocalJobDetailsRepository(resultsFilePath);
                container.RegisterInstance<IJobDetailsRepository>(repository);
            }
            else
            {
                //use WCF repository
                container.RegisterType<IJobDetailsRepository, RemoteJobDetailsRepository>();
            }

            //job service proxy
            container.RegisterType<WCFProxyFactory, AuthenticatedWCFProxyFactory>(new ContainerControlledLifetimeManager());
            WCFProxyFactory wcfProxyFactory = container.Resolve<WCFProxyFactory>();
            wcfProxyFactory.RegisterProxyType<SharedGenomics.Workbench.DataService.IDataService, SharedGenomics.Workbench.DataService.DataServiceClient>();
            wcfProxyFactory.RegisterProxyType<SharedGenomics.Workbench.FilterService.IFilterService, SharedGenomics.Workbench.FilterService.FilterServiceClient>();
            wcfProxyFactory.RegisterProxyType<SharedGenomics.Workbench.JobService.IJobService, SharedGenomics.Workbench.JobService.JobServiceClient>();
            wcfProxyFactory.RegisterProxyType<SharedGenomics.Workbench.AnnotationService.IAnnotationService, SharedGenomics.Workbench.AnnotationService.AnnotationServiceClient>();
            wcfProxyFactory.RegisterProxyType<SharedGenomics.Workbench.AnnotationSessionService.IAnnotationSessionService, SharedGenomics.Workbench.AnnotationSessionService.AnnotationSessionServiceClient>();

            //web services
            container.RegisterType<ISnpService, WCFSnpService>();
            container.RegisterType<IFileSetUploadService, WCFFileSetUploadService>();
            container.RegisterType<IDataFilterService, DataFilterService>();
            container.RegisterType<IJobService, WCFJobService>();
            container.RegisterType<IDataService, WCFDataService>();
            container.RegisterType<IAnnotationService, WCFAnnotationService>();
            container.RegisterType<IAnnotationSessionService, WCFAnnotationSessionService>();
            container.RegisterType<IAnalysisResultsLocator, RemoteAnalysisResultsLocator>();

            //add interceptors for services
            var interfaceInterceptionTypes = new[] { typeof(ISnpService), typeof(IFileSetUploadService), typeof(IJobService),
                typeof(IDataService), typeof(IAnnotationService), typeof(IAnnotationSessionService) };

            interfaceInterceptionTypes.ForEach(it => {
                container.Configure<Interception>().SetDefaultInterceptorFor(it, new InterfaceInterceptor());
            });
            //container.Configure<Interception>().SetDefaultInterceptorFor<ISnpService>(new InterfaceInterceptor());
            //container.Configure<Interception>().SetDefaultInterceptorFor<IFileSetUploadService>(new InterfaceInterceptor());
            //container.Configure<Interception>().SetDefaultInterceptorFor<IJobService>(new InterfaceInterceptor());
            //container.Configure<Interception>().SetDefaultInterceptorFor<IDataService>(new InterfaceInterceptor());
            //container.Configure<Interception>().SetDefaultInterceptorFor<IAnnotationService>(new InterfaceInterceptor());
            //container.Configure<Interception>().SetDefaultInterceptorFor<IAnnotationSessionService>(new InterfaceInterceptor());

            //setup annotation request types and manager
            container.RegisterType<IAnnotationSessionManager, RemotingAnnotationSessionManager>();
            container.RegisterType<IAnnotationImageUploader, AnnotationImageUploader>();
            container.RegisterType<AnnotationManager>(new ContainerControlledLifetimeManager());

#if HAS_VIEWED_ANNOTATIONS
            container.RegisterType<IAnnotationNotifier, RecordingAnnotationNotifier>(new ContainerControlledLifetimeManager());
#else
            container.RegisterType<IAnnotationNotifier, InertAnnotationNotifier>(new ContainerControlledLifetimeManager());
#endif

            //ensure the annotation notider is constructed...
            container.Resolve<IAnnotationNotifier>();
        }
    }
}
